package model.strategys.resolucao;

import model.cubos.Adesivo;
import model.cubos.Cor;
import model.cubos.CuboMagico3x3x3;
import model.rotations.Rotations;

public class ResolveMeio extends Estrategia{

	public ResolveMeio(Rotations rotacao) {
		super(rotacao);
	}
	
	public void resolveMeio(CuboMagico3x3x3 cubo) {

		boolean isLayerTwoReady = false;
		boolean isGoingToRotateLeft = false;
		int k = 0;
		int cont = 0;

		Adesivo[][][] matriz = cubo.getCubo();

		while (!isLayerTwoReady) {

			isLayerTwoReady = true;
			if (matriz[0][1][1].isCor(Cor.AZUL)||matriz[0][1][1].isCor(Cor.VERMELHO)) {
				if(matriz[0][1][1].isCor(Cor.AZUL))
					k=3;
				if(matriz[0][1][1].isCor(Cor.VERMELHO))
					k = 12;
				for (int i = 0; i < 4; i = i + 2) {
					if ((matriz[i][1][0].getKey() != k)
							|| (matriz[i][1][2].getKey() != k + 2)) {
						isLayerTwoReady = false;
					}
					k = k + 18;
				}
			}

			if (matriz[0][1][1].isCor(Cor.VERDE)||matriz[0][1][1].isCor(Cor.LARANJA)){
				if(matriz[0][1][1].isCor(Cor.VERDE))
					k = 21;
				if(matriz[0][1][1].isCor(Cor.LARANJA))
					k=30;
				for (int i = 0; i < 4; i = i + 2) {
					if ((matriz[i][1][0].getKey() != k)
							|| (matriz[i][1][2].getKey() != k + 2)) {
						isLayerTwoReady = false;
					}
					k = k - 18;
				}
			}

			cont = 0;
			if (!isLayerTwoReady) {

				for (int j = 0; j < 4; j++) {
					if (matriz[j][0][1].isCor(Cor.AMARELO))
						cont++;
				}
				if (matriz[4][0][1].isCor(Cor.AMARELO)
						|| matriz[4][1][0].isCor(Cor.AMARELO)
						|| matriz[4][1][2].isCor(Cor.AMARELO)
						|| matriz[4][2][1].isCor(Cor.AMARELO))
					cont++;
			}

			if ((cont < 4) && (!isLayerTwoReady)) {
				isGoingToRotateLeft = true;

				while (matriz[0][0][1].isCor(Cor.AMARELO) ||
						matriz[4][2][1].isCor(Cor.AMARELO)) {
					rotacao.girarCimaSentidoHorario(cubo);
				}

				if ((matriz[0][0][1].getKey() == 3) || (matriz[0][0][1].getKey() == 5)) {

					if (!(matriz[0][1][1].isCor(Cor.AZUL))) {

						while (!matriz[0][1][1].isCor(Cor.AZUL)) {
							rotacao.girarBaseSentidoHorario(cubo);
							rotacao.girarCamadaMeioHorizontalSentidoHorario(cubo);
						}

					}
					if (matriz[0][0][1].getKey() == 3)
						isGoingToRotateLeft = true;
					else if (matriz[0][0][1].getKey() == 5)
						isGoingToRotateLeft = false;
				} else {
					if ((matriz[0][0][1].getKey() == 12)
							|| (matriz[0][0][1].getKey() == 14)) {
						if (!(matriz[0][1][1].getKey() == 13)) {
							while (matriz[0][1][1].getKey() != 13) {
								rotacao.girarBaseSentidoHorario(cubo);
								rotacao.girarCamadaMeioHorizontalSentidoHorario(cubo);
							}
						}

						if (matriz[0][0][1].getKey() == 12)
							isGoingToRotateLeft = true;
						else if (matriz[0][0][1].getKey() == 14)
							isGoingToRotateLeft = false;
					} else {
						if ((matriz[0][0][1].getKey() == 21)
								|| (matriz[0][0][1].getKey() == 23)) {
							if (!(matriz[0][1][1].getKey() == 22)) {

								while (matriz[0][1][1].getKey() != 22) {
									rotacao.girarBaseSentidoHorario(cubo);
									rotacao.girarCamadaMeioHorizontalSentidoHorario(cubo);
								}
								
							}
							if (matriz[0][0][1].getKey() == 21)
								isGoingToRotateLeft = true;
							else if (matriz[0][0][1].getKey() == 23)
								isGoingToRotateLeft = false;
						} else {
							if ((matriz[0][0][1].getKey() == 30)
									|| (matriz[0][0][1].getKey() == 32)) {
								if (!(matriz[0][1][1].isCor(Cor.LARANJA))) {
									while (matriz[0][1][1].getKey() != 31) {
										rotacao.girarBaseSentidoHorario(cubo);
										rotacao.girarCamadaMeioHorizontalSentidoHorario(cubo);
									}
								}
								if (matriz[0][0][1].getKey() == 30)
									isGoingToRotateLeft = true;
								else if (matriz[0][0][1].getKey() == 32)
									isGoingToRotateLeft = false;
							}
						}
					}
				}

				if (isGoingToRotateLeft) {
					rotacao.girarCimaSentidoAntiHorario(cubo);
					resolveCamadaMeio_RotacaoPelaEsquerda(cubo);
				} else if (!isGoingToRotateLeft) {
						
						rotacao.girarCimaSentidoHorario(cubo);
						resolveCamadaMeio_RotacaoPelaDireita(cubo);
				}
			} else {
				// flag3=0;
				if ((cont == 4) && (!isLayerTwoReady)) {
					isGoingToRotateLeft = false;
					if (matriz[0][1][1].isCor(Cor.AZUL)
							|| matriz[0][1][1].isCor(Cor.VERMELHO)) {
						if (matriz[0][1][1].isCor(Cor.AZUL)){
							k = 3;
						}
						if (matriz[0][1][1].isCor(Cor.VERMELHO)){
							k = 12;
						}

						for (int i = 0; i < 4; i = i + 2) {
							isGoingToRotateLeft = resolveCamadaMeio_VerificarPecaCorrespondente(cubo, 
									matriz, i, k, isGoingToRotateLeft);
							k = k + 18;
						}
					}

					if (matriz[0][1][1].isCor(Cor.VERDE)
							|| matriz[0][1][1].getKey() == 31) {
						
						if (matriz[0][1][1].isCor(Cor.VERDE)){
							k = 21;
						}
						
						if (matriz[0][1][1].getKey() == 31){
							k = 30;
						}

						for (int i = 0; i < 4; i = i + 2) {
							isGoingToRotateLeft = resolveCamadaMeio_VerificarPecaCorrespondente(cubo, 
									matriz, i, k, isGoingToRotateLeft);
							k = k - 18;
						}
					}

					if (isGoingToRotateLeft) {
						resolveCamadaMeio_RotacaoPelaEsquerda(cubo);
					} else if (!isGoingToRotateLeft) {
						resolveCamadaMeio_RotacaoPelaDireita(cubo);
					}

				}
			}
		}
	}

	private void resolveCamadaMeio_RotacaoPelaDireita(CuboMagico3x3x3 cubo) {
		rotacao.girarDireitaSentidoHorario(cubo);
		rotacao.girarCimaSentidoHorario(cubo);
		rotacao.girarDireitaSentidoAntiHorario(cubo);
		rotacao.girarCimaSentidoAntiHorario(cubo);
		rotacao.girarEixoYSentidoHorario(cubo);
		rotacao.girarEsquerdaSentidoAntiHorario(cubo);
		rotacao.girarCimaSentidoAntiHorario(cubo);
		rotacao.girarEsquerdaSentidoHorario(cubo);
	}

	private void resolveCamadaMeio_RotacaoPelaEsquerda(CuboMagico3x3x3 cubo) {
		rotacao.girarEsquerdaSentidoAntiHorario(cubo);
		rotacao.girarCimaSentidoAntiHorario(cubo);
		rotacao.girarEsquerdaSentidoHorario(cubo);
		rotacao.girarCimaSentidoHorario(cubo);
		rotacao.girarEixoYSentidoAntiHorario(cubo);
		rotacao.girarDireitaSentidoHorario(cubo);
		rotacao.girarCimaSentidoHorario(cubo);
		rotacao.girarDireitaSentidoAntiHorario(cubo);
	}

	private boolean resolveCamadaMeio_VerificarPecaCorrespondente(CuboMagico3x3x3 cubo, Adesivo[][][] matriz, int i, int k, boolean isGoingToRotateLeft) {
		if ((matriz[i][1][0].getKey() != k)
				|| (matriz[i][1][2].getKey() != k + 2)) {
			if (matriz[i][1][0].getKey() != k && i == 0)
				isGoingToRotateLeft = true;
			else if (matriz[i][1][2].getKey() != k + 2 && i == 0)
				isGoingToRotateLeft = false;
			else if (matriz[i][1][0].getKey() != k && i == 2) {
				isGoingToRotateLeft = true;

				rotacao.girarEixoYSentidoHorario(cubo);
				rotacao.girarEixoYSentidoHorario(cubo);
			} else if (matriz[i][1][2].getKey() != k + 2 && i == 2) {
				isGoingToRotateLeft = false;

				rotacao.girarEixoYSentidoHorario(cubo);
				rotacao.girarEixoYSentidoHorario(cubo);
			}
		}
		return isGoingToRotateLeft;
	}
	

}
